<?php
/**
 * Category
 *
 * Обработка данных каиегорий
 *
 * @author Mike
 */
class Category extends ActiveRecord  {
	protected $tableName = 'category';
	public $pkName = 'ID_category';
	private static $arrAllCategories = null;	// Массив всех категорий
	
	protected $arrSettings = array('created_at' => true, 'author' => true, 'updated_at' => true);

	public $validatesLengthOf = array(
			'category_name' => array('min' => 2, 'max' => 256, 'message' => 'Название - 2-256 символов'),
			'description' => array('min' => 2, 'max' => 5000, 'message' => 'Описание - 2-5000 символов', 'allowNull' => true),
			'meta_description' => array('min' => 2, 'max' => 400, 'message' => 'Meta description - 2-400 символов','allowNull' => true),
			'meta_keywords' => array('min' => 2, 'max' => 400, 'message' => 'Meta keywords - 2-400 символов', 'allowNull' => true),
			'url' => array('min' => 1, 'max' => 64, 'message' => 'URL - от 1 до 64 символов')
	);
	
	public $validatesFormatOf = array(
			'url' => array('with' => '/^[\-_a-z0-9\.]+$/ui', 'message' => 'URL заполнен неверно')
	);
	
	public $validatesUniquenessOf = array(
			'url' => array('message' => 'Такой URL уже используется')
	);
	
	public function beforeValidation() {
		if(!empty($this->tableFields['ID_parent_category'])) {
			$arrAvailableCategoriesIds = $this->getCategoriesAvailableAsParent();
			if(!array_key_exists($this->getField('ID_parent_category'), $arrAvailableCategoriesIds)) $this->errorValidated('', 'Недопустимая родительская категория');
		}
	}
	
	/**
	 * Метод формирует дерево категорий
	 * @param array $arrCategories - массив категорий
	 */
	public static function getCategoriesTree(array &$arrCategories) {
		$arrParentCategories = array();
		
		// Получаем массив главных категорий (без родителей)
		foreach($arrCategories as $key => &$arrCategory) {
			if(!$arrCategory['ID_parent_category']) $arrParentCategories[] = $arrCategory;
			unset($arrCategory);
		}
		
		// Перебираем главных родителей
		foreach($arrParentCategories as &$arrParentCategory) {
			self::getCategoryChildren($arrParentCategory, $arrCategories);
		}
		
		return $arrParentCategories;
	}
	
	/**
	 * Метод для переданной категории строит дерево её детей
	 * 
	 * @param array $arrParentCategory - массив категории, дети которой строятся
	 * @param array $arrCategories - массив всех категорй
	 */
	public static function getCategoryChildren(array &$arrParentCategory, array &$arrCategories) {
		foreach($arrCategories as &$arrCategory) {
			if($arrCategory['ID_parent_category'] == $arrParentCategory['ID_category']) {
				$arrParentCategory['children'][] = &$arrCategory;
				self::getCategoryChildren($arrCategory, $arrCategories);
			}
		}
	}
	
	/**
	 * Метод получает категории, которые могут выступать родителями для других категорий
	 * Такие категории, к которым не привязаны напрямую товары
	 */
	public function getCategoriesAvailableAsParent() {
		$objDB = Service_Database::instanse();
		$stmt = "SELECT `category`.`ID_category`, `category`.`category_name`
				FROM `category`
				LEFT JOIN `product` USING(`ID_category`)
				WHERE `product`.`ID_product` IS NULL" . ($this->id ? " AND `category`.`ID_category` !='" . $this->id . "'" : '');
		return Service_ArrayConverter::makeKeySimpleArrayFromMultyArray($objDB->select($stmt), 'ID_category', 'category_name');
	}
	
	/**
	 * Получает список товаров текущей кактегории.
	 * Если текущая категория иммет дочерние категории, то получим список товаров всех дочерних категорий.
	 */
	public function getCategoryProducts() {
		$objDB = Service_Database::instanse();
		$arrCategoriesIds = array($this->id);	// Массив айдшников категорий для которых будем получать товары
		
		$stmt = "SELECT `category`.`ID_category`, `category`.`ID_parent_category`
				FROM `category`
				WHERE `category`.`ID_parent_category` IS NOT NULL";
		$arrCategories = $objDB->select($stmt);
		
		// Получаем дочерние категории для текущей категории
		self::getCategoryChildren($this->tableFields, $arrCategories);
		
		
		if(isset($this->tableFields['children'])) { // Если у текущей категории есть дочерние категории, дописываем их айдшники для последующего поиска
			$arrCategoriesIds = array_merge($arrCategoriesIds, self::getCategoryChildrenIds($this->tableFields['children']));
		}

		$stmt = "SELECT `product`.*
				FROM `product`
				WHERE `product`.`ID_category` IN(" . implode(',', $arrCategoriesIds) . ")
				ORDER BY `product`.`created_at` DESC";
		return $objDB->select($stmt);
	}
	
	/**
	 * Получает айдишники дочерних категорий
	 * 
	 * @param array $arrChildren - древовидный массив дочерних категорий
	 */
	public static function getCategoryChildrenIds(array &$arrChildren) {
		$arrChildrenIds = array();
		foreach($arrChildren as $arrChild) {
			$arrChildrenIds[] = $arrChild['ID_category'];
			if(isset($arrChild['children'])) $arrChildrenIds = array_merge($arrChildrenIds, self::getCategoryChildrenIds($arrChild['children']));
		}
		return $arrChildrenIds;
	}
	
	/**
	 * Формирует массив категорий для вывода в левом меню на страницах категории
	 */
	public function getCategoriesForLeft() {
		$objDB = Service_Database::instanse();
		$arrResultCategories = array();
		
		// Все категории
		$stmt = "SELECT `category`.`ID_category`, `category`.`ID_parent_category`, `category`.`url`, `category`.`category_full_name` 
				FROM `category`";
		$arrAllCategories = $objDB->select($stmt);
		$arrAllCategories = Service_ArrayConverter::makeKeyArrayFromMultyArray($arrAllCategories, 'ID_category');
		
		// Категория-листья, с которых начинаем поиск
		$stmt = "SELECT DISTINCT `product`.`ID_category`
				FROM `product`
				WHERE `product`.`ID_category` IS NOT NULL";
		$arrCategoriesLeafsIds = $objDB->selectOneColumn($stmt);

		foreach($arrCategoriesLeafsIds as $categoryId) {
			$arrResultCategories[] = $arrAllCategories[$categoryId];
			$arrResultCategories = array_merge($arrResultCategories, self::getCategoryParents($arrAllCategories[$categoryId], $arrAllCategories));
		}

		return Category::getCategoriesTree($arrResultCategories);
	}
	
	/**
	 * Получает массив родителей категории
	 */
	public static function getCategoryParents(&$arrCategory, &$arrAllCategories) {
		$arrParentCategories = array();
		if($arrCategory['ID_parent_category']) {
			$arrParentCategories[] = $arrAllCategories[$arrCategory['ID_parent_category']];
			$arrParentCategories = array_merge($arrParentCategories, self::getCategoryParents($arrAllCategories[$arrCategory['ID_parent_category']], $arrAllCategories));
		}
		
		return $arrParentCategories;
	}
	
	/**
	 * Формирует массив данных хлебных крошек для категории с заданным id
	 * 
	 * param $categoryId - id категории для которой получаем крошки
	 */
	public static function getCategoryCrumbs($categoryId) {
		$arrAllCategories = self::getAllCategories();
		$arrCategory = $arrAllCategories[$categoryId];
		$arrCategories = array_merge(self::getCategoryParents($arrCategory, $arrAllCategories), array($arrCategory));
		return $arrCategories;
	}
	
	public static function getAllCategories() {
		if(self::$arrAllCategories === null) {
			$objDB = Service_Database::instanse();
				
			$stmt = "SELECT `category`.`ID_category`, `category`.`ID_parent_category`, `category`.`url`, `category`.`category_name`
				FROM `category`";
			self::$arrAllCategories = Service_ArrayConverter::makeKeyArrayFromMultyArray($objDB->select($stmt), 'ID_category');
		}
	
		return self::$arrAllCategories;
	}
}